package org.tissou.server.importer;

import org.tissou.client.Services.*;

import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.tissou.server.Utils.InterfaceMySQL;
import org.tissou.server.Utils.Variables_Globales;
import org.tissou.server.Base.Categorie;
import org.tissou.server.Base.Proprietaire;

/**
 * Cette classe genere une liste d'operation en suivant des regles
 * simples, a partir de la liste generee par un importeur de transactions.
 */
public class GenerateurOperationSimple implements GenerateurOperation {

  private ImporteurDeTransactions importeur;

  private InterfaceMySQL interfacePourLesRequetes;
  private Compte compte;
  private Map<String, String> categorieMappings;
  private boolean initialise = false;
  private Map<String, String> tiersMapping;

  public GenerateurOperationSimple(ImporteurDeTransactions importer) {
    importeur = importer;
    interfacePourLesRequetes = new InterfaceMySQL();
  }

  void initialiser() {
    compte = obtenirLeCompte();
    categorieMappings = obtenirMappingLibelleVersCategorie();
    initialise = true;
    tiersMapping = obtenirMappingCategorieVersTiers();
  }

  protected Compte obtenirLeCompte() {
    String requete = String.format(
        "SELECT NoCompte FROM IdentifiantDesComptes WHERE Identifiant = '%s'",
        importeur.identifiantCompte());
    try {
      ResultSet result = interfacePourLesRequetes.RecupererDonnees(requete);
      if (!result.next()) {
        // le resultat est vide
        throw new MonException(String.format(
            "Je ne connais pas ce compte : %s", importeur.identifiantCompte()));
      }
      int noCompte = result.getInt(1);
      return Variables_Globales.ListeProprietaire.ObtenirCompte(noCompte);
    } catch (SQLException e) {
      throw new MonException("Probleme avec la requete. Verifiez que la table IdentifiantDesComptes existe");
    }
  }

  protected Map<String, String> obtenirMappingLibelleVersCategorie() {
    Map<String, String> categorieMapping = new HashMap<String, String>();
    String requete = "SELECT * FROM CategoriesMapping";
    try {
      ResultSet result = interfacePourLesRequetes.RecupererDonnees(requete);
      while(result.next()) {
        String libelle = result.getString(1);
        String categorie = result.getString(2);
        categorieMapping.put(libelle, categorie);
      }
    } catch (SQLException e) {
      e.printStackTrace();
      throw new MonException("Probleme avec la requete. Verifiez que la table CategoriesMapping existe");
    }
    return categorieMapping;
  }

  protected Map<String, String> obtenirMappingCategorieVersTiers() {
    Map<String, String> mapping = new HashMap<String, String>();
    String requete = String.format("SELECT * FROM TiersMapping WHERE NoCompte = '%d'",
        compte.getNoCompte());
    try {
      ResultSet result = interfacePourLesRequetes.RecupererDonnees(requete);
      while(result.next()) {
        String libelle = result.getString(1);
        String categorie = result.getString(2);
        mapping.put(libelle, categorie);
      }
    } catch (SQLException e) {
      throw new MonException("Probleme avec la requete. Verifiez que la table CategoriesMapping existe");
    }
    return mapping;
  }

  public Parametres genererUneOperation(Parametres params) {
    if (!initialise) {
      initialiser();
    }
    List<Compte> comptes = new ArrayList<Compte>();
    comptes.add(compte);
    if (categorieMappings.containsKey(params.getLibelles().get(0))) {
      Categorie categorie = Variables_Globales.Tout.rechercherCategorieDansDescendance(
          categorieMappings.get(params.getLibelles().get(0)));
      params.ajouterCategorie(
          categorie.getInfos());
    } else {
      // TODO(manu): C'est un peu pourri ca de metre tout quand on sait pas quoi faire
      params.ajouterCategorie(Variables_Globales.Tout.rechercherCategorieDansDescendance("Divers").getInfos());
    }
    if (tiersMapping.containsKey(params.getCategories().get(0).getNom())) {
      float somme = params.getSommes().get(0);
      Proprietaire tiers = Variables_Globales.ListeProprietaire.ObtenirProprietaire(
          tiersMapping.get(params.getCategories().get(0).getNom()));
      params.ajouterDette(
          new Dette(compte.getProprio(), tiers.getInfos(), somme / 2));
    }

    params.setTypeoperation(OperationFactoryInfos.TypeOperation.OPERATION_DEPENSE);
    params.setComptes(comptes);
    return params;
  }

  public List<Parametres> genererOperations() {
    List<Parametres> tousLesParametres = new ArrayList<Parametres>();
    for (Parametres params : importeur.toutesLesTransactions()) {
      tousLesParametres.add(genererUneOperation(params));
    }
    return tousLesParametres;
  }
}
